package com.tjc.connPool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;

public class ConnPoolExecuter {

    private static final int ESTABLISHED = 1;
    private static final int STOP = 4;

    private DataSourceConfig config;
    private int status = 0;

    private int minConnet;
    private int maxConnect;
    private int lifeTime;
    private int reconnect;
    private AtomicInteger activeNum = new AtomicInteger(0);

    //需要同步容器,而且ele应该是一个有conn的包装类
    LinkedBlockingDeque<Connection> connPool = null;
    LinkedBlockingDeque<Connection> busyPool = null;

    public ConnPoolExecuter(DataSourceConfig config, int minSize, int maxSize, int liftTime) {
        this.config = config;
        this.minConnet = minSize;
        this.maxConnect = maxSize;
        this.lifeTime = liftTime;

        start();
        System.out.format("pool size: %d\n", connPool.size());
    }

    public void start() {
        connPool = new LinkedBlockingDeque<>(this.maxConnect);
        busyPool = new LinkedBlockingDeque<>(this.maxConnect);
        int i = 0;
        try {
            while (i++ < minConnet && connPool.add(buildConnection())) ;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        activeNum.set(connPool.size());
    }

    public void close() throws SQLException {
        setStatus(STOP);
        for (Connection conn : connPool)
            if (!conn.isClosed())
                conn.close();
        connPool.clear();
    }

    public Connection getConnection() {
        //poll是线程安全的
        Connection conn = connPool.poll();
        //连接池已空，未达到最大连接数，新建连接
        if (conn == null) {
            if (this.activeNum.incrementAndGet() <= maxConnect) {
                try {
                    conn = buildConnection();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            } else {
                activeNum.decrementAndGet();
                try {
                    conn = connPool.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        busyPool.add(conn);
        System.out.format("获取连接，busyPool: %d，connPool: %d\n", busyPool.size(), connPool.size());
        return conn;
    }


    private Connection buildConnection() throws SQLException {
        return DriverManager.getConnection(config.getUrl(), config.getUser(), config.getPassword());
    }

    public void recycle(Connection conn) {
        try {
            if (conn == null || conn.isClosed())
                return;
            connPool.add(conn);
            busyPool.remove(conn);
            System.out.format("归还连接，busyPool: %d, connPool: %d\n", busyPool.size(), connPool.size());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private void setStatus(int stopStatus) {
        this.status = stopStatus;
    }
}
